#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "timers.h"
#include "mpi.h"


long int recTimer();

main(int argc, char **argv)
{	
		int len = 20000000;
		long int time_start = recTimer();
		if(argc>1) {rand()/1000000
			len = (int) strtol(argv[1], NULL, 10);

		}
	
        int np, rank;
        MPI_Status status;

        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &np);
        double *liczba;
        double *divliczba;
        
        

        int counter = 0;
        int wynik = 0;

        liczba = (double*)malloc(sizeof(*liczba)*len*np);
        divliczba = (double*)malloc(sizeof(*divliczba)*len);

        if(rank==0) {
                unsigned int iseed = (unsigned int)time(NULL);
                srand (rank + iseed);
                int i;
                if(rank == 0) {
                        for(i=0; i<(len*np); i++) {

                                liczba[i] = (double)rand()/RAND_MAX;

                        }

                }
        }

        MPI_Scatter(liczba, len, MPI_DOUBLE, divliczba, len, MPI_DOUBLE, 0,MPI_COMM_WORLD);
        free(liczba);
        long int process_time = recTimer();
        int j;
        for(j=0; j<(len/2); j++) {

                if((double)pow(divliczba[j],2) + (double)pow(divliczba[j+(len/2)],2)<1) {
                        counter++;
                }

        }
        printf("Proces (%d): %0.4f s \n", rank, (double)(recTimer() - process_time)/1000000000);
        free(divliczba);
        long int recTimer() {
        	struct timespec t;
        	clock_gettime(CLOCK_MONOTONIC, &t);
        	return ((t.tv_sec * TIMER_SCALE) + t.tv_nsec);
        }
        MPI_Reduce(&counter, &wynik, 1, MPI_INT,MPI_SUM, 0, MPI_COMM_WORLD);
       // MPI_BARRIER(MPI_COMM_WORLD);
        if(rank==0) {

                printf("PI wynosi około: %f \n", (double)4* wynik/(np*(len/2)));
        }

        MPI_Finalize();
        
        if(rank==0) {
        	
        	printf("Czas całego programu: %f \n", (double)(recTimer()-time_start) / 1000000000);
        }
}

long int recTimer() {
	struct timespec t;
	clock_gettime(CLOCK_MONOTONIC, &t);
	return ((t.tv_sec * TIMER_SCALE) + t.tv_nsec);
}
